/*
* Copyright (C) 2021 THL A29 Limited, a Tencent company.  All rights reserved.
* This source code is licensed under the Apache License Version 2.0.
 */

package routers

import (
	"nocalhost/pkg/nocalhost-api/app/api/v1/application_cluster"
	"nocalhost/pkg/nocalhost-api/app/api/v1/application_user"
	"nocalhost/pkg/nocalhost-api/app/api/v1/applications"
	"nocalhost/pkg/nocalhost-api/app/api/v1/cluster"
	"nocalhost/pkg/nocalhost-api/app/api/v1/cluster_user"
	"nocalhost/pkg/nocalhost-api/app/api/v1/ldap"
	"nocalhost/pkg/nocalhost-api/app/api/v1/service_account"
	"nocalhost/pkg/nocalhost-api/app/api/v1/version"
	"nocalhost/pkg/nocalhost-api/napp"

	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"

	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger" //nolint: goimports

	"nocalhost/pkg/nocalhost-api/app/api"
	"nocalhost/pkg/nocalhost-api/app/api/v1/user"

	// import swagger handler
	_ "nocalhost/docs" // docs is generated by Swag CLI, you have to import it.
	"nocalhost/pkg/nocalhost-api/app/router/middleware"
)

// Load loads the middlewares, routes, handlers.
func Load(g *gin.Engine, mw ...gin.HandlerFunc) *gin.Engine {
	// 使用中间件
	g.Use(middleware.NoCache)
	g.Use(middleware.Options)
	g.Use(middleware.Secure)
	g.Use(middleware.Logging())
	g.Use(middleware.RequestID())
	g.Use(mw...)

	// 404 Handler.
	g.NoRoute(api.RouteNotFound)
	g.NoMethod(api.RouteNotFound)
	g.Use(api.Recover)

	// Static resources
	//g.Static("/static", "./static")

	// Open only in the test environment, close online
	if viper.GetString("app.run_mode") == napp.ModeDebug {
		// swagger api docs
		g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
		// pprof router Performance analysis routing
		// Closed by default, can be opened in development environment
		// interview method: HOST/debug/pprof
		// Generate profile through HOST/debug/pprof/profile
		// View analysis graph go tool pprof -http=:5000 profile
		// see: https://github.com/gin-contrib/pprof
		pprof.Register(g)
	} else {
		// disable swagger docs for release  env=release
		g.GET("/swagger/*any", ginSwagger.DisablingWrapHandler(swaggerFiles.Handler, "env"))
	}
	// version
	g.GET("/v1/version", version.Get)

	g.POST("/v1/register", user.Register)
	g.POST("/v1/login", user.Login)
	g.POST("/v1/token/refresh", user.RefreshToken)

	u := g.Group("/v1/users")
	u.Use(middleware.AuthMiddleware(), middleware.PermissionMiddleware())
	{
		u.GET("/:id", user.Get)
		u.GET("", user.GetList)
		u.POST("", user.Create)
		u.PUT("/:id", user.Update)
		u.POST("/import", user.Import)
		u.GET("/import_status/:id", user.ImportStatus)
		u.DELETE("/:id", user.Delete)
		u.GET("/:id/dev_space_list", cluster_user.GetJoinClusterAndAppAndUser)
		u.GET("/:id/applications", applications.ListPermitted)
		u.GET("/:id/dev_spaces", cluster_user.ListByUserId)
		u.GET("/:id/clusters", cluster.ListByUser)
	}

	m := g.Group("/v1/me")
	m.Use(middleware.AuthMiddleware())
	{
		m.GET("", user.GetMe)
	}

	// Clusters
	c := g.Group("/v1/cluster")
	c.Use(middleware.AuthMiddleware(), middleware.PermissionMiddleware())
	{
		c.POST("", cluster.Create)
		c.GET("", cluster.GetList)
		c.GET("/:id/dev_space", cluster.GetSpaceList)
		c.GET("/:id/dev_space/:space_id/detail", cluster.GetSpaceDetail)
		c.GET("/:id/detail", cluster.GetDetail)
		c.DELETE("/:id", cluster.Delete)
		c.GET("/:id/storage_class", cluster.GetStorageClass)
		c.POST("/:id/storage_class", cluster.GetStorageClassByKubeConfig)
		c.PUT("/:id", cluster.Update)
		c.GET("/:id/gen_namespace", cluster.GenNamespace)
		c.PUT("/:id/migrate", cluster.Migrate)
	}

	// Applications
	a := g.Group("/v1/application")
	a.Use(middleware.AuthMiddleware(), middleware.PermissionMiddleware())
	{
		a.POST("", applications.Create)
		a.GET("", applications.Get)
		a.GET("/:id", applications.GetDetail)
		a.DELETE("/:id", applications.Delete)
		a.PUT("/:id", applications.Update)
		a.PUT("/:id/public", applications.PublicSwitch)
		a.POST("/:id/bind_cluster", application_cluster.Create)
		a.GET("/:id/bound_cluster", application_cluster.GetBound)
		a.GET("/:id/dev_space", cluster_user.GetFirst)
		a.GET("/:id/dev_space/:space_id/detail", cluster_user.GetDevSpaceDetail)
		a.GET("/:id/dev_space_list", cluster_user.GetList)
		a.GET("/:id/cluster/:clusterId", applications.GetSpaceDetail)
		a.GET("/:id/users", user.ListByApplication)
		a.GET("/:id/!users", user.ListNotInApplication)
		a.POST("/:id/users", application_user.BatchInsert)
		a.DELETE("/:id/users", application_user.BatchDelete)
	}

	// nocalhost
	n := g.Group("/v1/nocalhost")
	n.Use(middleware.AuthMiddleware(), middleware.PermissionMiddleware())
	{
		n.GET("/templates", applications.GetNocalhostConfigTemplate)
		n.GET("/version/upgrade_info", version.UpgradeInfo)
	}

	dv2 := g.Group("/v2/dev_space")
	dv2.Use(middleware.AuthMiddleware(), middleware.PermissionMiddleware())
	{
		dv2.GET("", cluster_user.ListV2)
		dv2.GET("/cluster", cluster.GetDevSpaceClusterList)
		dv2.GET("/detail", cluster_user.GetV2)
		dv2.GET("/ns_list", cluster_user.GetNsInfo)
		dv2.POST("/ns_import", cluster_user.NsImport)
		dv2.POST("/ns_batch_import", cluster_user.NsBatchImport)
		dv2.GET("/ns_import_status/:id", cluster_user.ImportStatus)
		dv2.POST("/share", cluster_user.Share)
		dv2.POST("/unshare", cluster_user.UnShare)
	}

	// DevSpace
	dv := g.Group("/v1/dev_space")
	dv.Use(middleware.AuthMiddleware(), middleware.PermissionMiddleware())
	{
		dv.POST("", cluster_user.Create)
		dv.GET("", cluster_user.ListAll)
		dv.DELETE("/:id", cluster_user.Delete)
		dv.PUT("/:id", cluster_user.Update)
		dv.POST("/:id/recreate", cluster_user.ReCreate)
		dv.GET("/:id/detail", cluster_user.GetJoinClusterAndAppAndUserDetail)
		dv.PUT("/:id/update_resource_limit", cluster_user.UpdateResourceLimit)
		dv.PUT("/:id/update_mesh_dev_space_info", cluster_user.UpdateMeshDevSpaceInfo)
		dv.GET("/:id/mesh_apps_info", cluster_user.GetAppsInfo)
	}

	l := g.Group("/v1/ldap")
	l.Use(middleware.AuthMiddleware(), middleware.PermissionMiddleware())
	{
		l.GET("/config", ldap.GetConfiguration)
		l.PUT("/config/set", ldap.Configuration)
		l.PUT("/config/disable", ldap.DeleteConfiguration)
		l.PUT("/bind", ldap.TestBind)
		l.PUT("/search", ldap.TestSearch)
		l.POST("/trigger", ldap.Trigger)
	}

	// Plug-in
	pa := g.Group("/v1/plugin")
	pa.Use(middleware.AuthMiddleware())
	{
		pa.GET("/service_accounts", service_account.ListAuthorization)
		pa.GET("/dev_space", applications.PluginGet)
		pa.POST("/:id/recreate", cluster_user.PluginReCreate)
		pa.PUT("/application/:id/dev_space/:spaceId/plugin_sync", applications.UpdateApplicationInstall)
	}

	return g
}
